#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <stdbool.h>

char password[20], password_check[20];
int ascii_encoded, h;
FILE *fp;
struct hash_array_node {
	char username[30];
	char password[30];
} hash_array[97] = {0};


//_____________________________________________________________________________________________________________________

int linear_probe(int i)
{
	return i + 1;
}


//_____________________________________________________________________________________________________________________


int quadratic_probe(int i)
{
	return i * i + 1;
}


//_____________________________________________________________________________________________________________________

int triple_probe(int i)
{
	return i * i*i + 1;
}

//_____________________________________________________________________________________________________________________

file_read_hashfunc_hash_table1(int (*linear_probe) (int))
{
	fp = fopen("database.txt", "r");
	if (fp == NULL) {
		puts("Cannot open file");
		exit(0);
	}

	int i = 0, j = 0, hash_value, k, hu, lp;
	char char_values, temp_u[30], temp_p[30];

	while (!feof(fp)) {
		fscanf(fp, "%s %s", temp_u, temp_p);
		//printf("%s %s\n", temp_u, temp_p);
		
		ascii_encoded = ascii_encoding(temp_u);
		hash_value = ascii_encoded % 97;

		lp = 0;
		while (hash_array[(hash_value + lp) % 97].username[0] != 0) {
			lp = linear_probe(lp);
		}
		
		hash_value = (hash_value + lp) % 97;
		strcpy(hash_array[hash_value].password, temp_u);
		strcpy(hash_array[hash_value].username, temp_p);
	}
	fclose(fp);
}

//_____________________________________________________________________________________________________________________
bool authenticate1(int (*linear_probe) (int))
{
	fgetc(stdin);
	char username_check[30];
	int hu, lp = 0,count=0;
	printf("Please enter your username \t  ");
	scanf("%s",username_check);
	
	hu = ascii_encoding(username_check);
	hu = hu % 97;
	
	while (hash_array[(hu + lp) % 97].username[0] != 0 && strcmp(hash_array[(hu + lp) % 97].username,username_check) != 0) {
		lp = linear_probe(lp);
	}

	hu = (hu + lp) % 97;

	if (strcmp(hash_array[hu].username, username_check) == 0) {
		printf("The username exists , Now please enter the password \n");
	} else {
		printf("Please enter the correct username \n");
		return false;
	}

	fgetc(stdin);
	char password_check[30];
	printf("Please enter the password to login \t ");
	scanf("%s", password_check);

	if (hash_array[(hu + lp) % 97].password[0] != 0 && strcmp(hash_array[hu].password, password_check) == 0) {
		printf("The password entered by you is correct. You are now logged in \n");
		return true;
	} else 
	{
		printf("Incorrect password or  wrong input for username \n");
		count++;
		hash_func();
		if(count==3){
		return false;
		}
	}

}
//_____________________________________________________________________________________________________________________



file_read_hashfunc_hash_table2(int (*quadratic_probe) (int))
{
	fp = fopen("database.txt", "r");
	if (fp == NULL) {
		puts("Cannot open file");
		exit(0);
	}
	int i = 0, j = 0, hash_value, k, hu, lp;
	char char_values, temp_u[30], temp_p[30];

	while (!feof(fp)) {
		fscanf(fp, "%s %s", temp_u, temp_p);
		//printf("%s %s\n", temp_u, temp_p);
		
		ascii_encoded = ascii_encoding(temp_u);
		hash_value = ascii_encoded % 97;

		lp = 0;
		while (hash_array[(hash_value + lp) % 97].username[0] != 0) {
			lp = quadratic_probe(lp);
		}
		
		hash_value = (hash_value + lp) % 97;
		strcpy(hash_array[hash_value].password, temp_u);
		strcpy(hash_array[hash_value].username, temp_p);
	}
	fclose(fp);
}

//_____________________________________________________________________________________________________________________

bool authenticate2(int (*quadratic_probe) (int))
{
	fgetc(stdin);
	char username_check[30];
	int hu, lp = 0,count=0;
	printf("Please enter your username \t  ");
	scanf("%s",username_check);
	
	hu = ascii_encoding(username_check);
	hu = hu % 97;
	
	while (hash_array[(hu + lp) % 97].username[0] != 0 && strcmp(hash_array[(hu + lp) % 97].username,username_check) != 0) {
		lp = quadratic_probe(lp);
	}

	hu = (hu + lp) % 97;

	if (strcmp(hash_array[hu].username, username_check) == 0) {
		printf("The username exists , Now please enter the password \n");
	} else {
		printf("Please enter the correct username \n");
		return false;
	}

	fgetc(stdin);
	char password_check[30];
	printf("Please enter the password to login \t ");
	scanf("%s", password_check);

	if (hash_array[(hu + lp) % 97].password[0] != 0 && strcmp(hash_array[hu].password, password_check) == 0) {
		printf("The password entered by you is correct. You are now logged in \n");
		return true;
	} else 
	{
		printf("Incorrect password or  wrong input for username \n");
		count++;
		hash_func();
		if(count==3){
		return false;
		}
	}

}

//_____________________________________________________________________________________________________________________

file_read_hashfunc_hash_table3(int (*triple_probe) (int))
{
	fp = fopen("database.txt", "r");
	if (fp == NULL) {
		puts("Cannot open file");
		exit(0);
	}
	int i = 0, j = 0, hash_value, k, hu, lp;
	char char_values, temp_u[30], temp_p[30];

	while (!feof(fp)) {
		fscanf(fp, "%s %s", temp_u, temp_p);
		//printf("%s %s\n", temp_u, temp_p);
		
		ascii_encoded = ascii_encoding(temp_u);
		hash_value = ascii_encoded % 97;

		lp = 0;
		while (hash_array[(hash_value + lp) % 97].username[0] != 0) {
			lp = triple_probe(lp);
		}
		
		hash_value = (hash_value + lp) % 97;
		strcpy(hash_array[hash_value].password, temp_u);
		strcpy(hash_array[hash_value].username, temp_p);
	}
	fclose(fp);
	
}

//_____________________________________________________________________________________________________________________

bool authenticate3(int (*triple_probe) (int))
{
	fgetc(stdin);
	char username_check[30];
	int hu, lp = 0,count=0;
	printf("Please enter your username \t  ");
	scanf("%s",username_check);
	
	hu = ascii_encoding(username_check);
	hu = hu % 97;
	
	while (hash_array[(hu + lp) % 97].username[0] != 0 && strcmp(hash_array[(hu + lp) % 97].username,username_check) != 0) {
		lp = triple_probe(lp);
	}

	hu = (hu + lp) % 97;

	if (strcmp(hash_array[hu].username, username_check) == 0) {
		printf("The username exists , Now please enter the password \n");
	} else {
		printf("Please enter the correct username \n");
		return false;
	}

	fgetc(stdin);
	char password_check[30];
	printf("Please enter the password to login \t ");
	scanf("%s", password_check);
	
	if (hash_array[(hu + lp) % 97].password[0] != 0 && strcmp(hash_array[hu].password, password_check) == 0) {
		printf("The password entered by you is correct. You are now logged in \n");
		return true;
	} else 
	{
		printf("Incorrect password or wrong input for username \n");
		count++;
		hash_func();
		if(count==3){
		return false;
		}
	}

}

//_____________________________________________________________________________________________________________________________

int ascii_encoding(char username[])
{

	int string_length, i, ascii, sum = 0;

	string_length = strlen(username);

	for (i = 0; i <= string_length - 1; i++) {
		ascii = username[i];
		sum = sum + ascii;
	}
	return sum;
}

//_____________________________________________________________________________________________________________________________
void file_write()
{
	FILE *fp;

	char username_password_input[80];

	fp = fopen("database.txt", "a");
	printf
	    ("\nWelcome new user , Please enter the username and password followed by a space\n");
	while (strlen(gets(username_password_input)) > 0) {
		fputs(username_password_input, fp);
	}
	fclose(fp);
}

//_____________________________________________________________________________________________________________________________-");

int hash_func()
{
	int option;
	printf("Which function do you want to implement \t \n");
	printf("case 1 : You opt for a normal hashing func with linear probing \n");
	printf("case 2 : You opt for normal hashing func with quadratic probing\n");
	printf("case 3 : You opt for a normal hashing func with trilinear probing \n");
	scanf("%d", &option);
	
	switch (option) {
	case 1:
		printf("You opted for normal hashing \n");
		file_read_hashfunc_hash_table1(linear_probe);
		authenticate1(linear_probe);
		break;
	case 2:
		printf(" You opted for normal hashing func with quadratic probing \n");
		file_read_hashfunc_hash_table2(quadratic_probe);
		authenticate2(quadratic_probe);
		break;
	case 3:
		printf("You opted for a normal hashing func with trilinear probing \n");
		file_read_hashfunc_hash_table3(triple_probe);
		authenticate3(triple_probe);
		break;

	}
}

//_____________________________________________________________________________________________________________________________-");

void main()
{

	int count = 0;
	char  newuser[20];

	printf("Are you a new user ? If yes then type yes else no \n");
	gets(newuser);

	if (strcmp(newuser, "yes") == 0)
	{
		file_write();
	}
	printf("\n");
	hash_func();

}
